package com.example.robertluozizhao.framecollectdemo.view;

import android.content.Context;
import androidx.customview.widget.ViewDragHelper;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;

/**
 * Created by robert.luozizhao on 2018/1/12.
 */

public class ScrollDeteleViewGroup extends ViewGroup {

    private final static String TAG = "diy";
    private View tvDelete;
    private View tvContant;
    private float downX;
    private float mDistance;
    private ViewDragHelper mViewDragHelper;

    public ScrollDeteleViewGroup(Context context) {
        this(context, null);
    }

    public ScrollDeteleViewGroup(Context context, AttributeSet attrs) {
        super(context, attrs);
    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        LayoutParams tvContantParams = tvContant.getLayoutParams();
        int contantHeight = MeasureSpec.makeMeasureSpec(tvContantParams.height, MeasureSpec.EXACTLY);
        tvContant.measure(widthMeasureSpec, contantHeight);

        LayoutParams tvDeleteParams = tvDelete.getLayoutParams();
        int deleteHeight = MeasureSpec.makeMeasureSpec(tvDeleteParams.height, MeasureSpec.EXACTLY);
        int deleteWidth = MeasureSpec.makeMeasureSpec(tvDeleteParams.width, MeasureSpec.EXACTLY);
        tvDelete.measure(deleteWidth, deleteHeight);
        setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
        Log.d(TAG, "onMeasure: tvContant --> Measuredheight:" + tvContant.getMeasuredHeight() + ",height" + tvContant.getHeight());
        Log.d(TAG, "onMeasure: tvDelete:--> MeasureWidth:" + tvDelete.getMeasuredWidth() + ",width:" + tvDelete.getWidth());
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        tvContant.layout(0, 0, tvContant.getMeasuredWidth(), tvContant.getMeasuredHeight());
        tvDelete.layout(tvContant.getMeasuredWidth(), 0, tvContant.getMeasuredWidth() + tvDelete.getMeasuredWidth(), tvDelete.getMeasuredHeight());
    }

/*//    scroll 实现滑动
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int action = event.getAction();
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                downX = event.getX() + 0.5f;
                break;
            case MotionEvent.ACTION_MOVE:
                float moveX = event.getX() + 0.5f;
                mDistance = downX - moveX;

                int scrollX = getScrollX();

                if (scrollX+ mDistance <0) {
                    //右滑动极限
                    scrollTo(0,0);
                }else if(scrollX+ mDistance >tvDelete.getWidth()){
                    //左滑动极限
                    scrollTo(tvDelete.getMeasuredWidth(),0);
                }else {
                    //正常滑动
                    scrollBy((int) mDistance,0);
                }

                downX = moveX;
                Log.d("diy", "onTouchEvent: tvDeleteWidth:"+tvDelete.getWidth()+",tvDeleteMeasuredWidth:"+tvDelete.getMeasuredWidth());
                Log.d("diy", "onTouchEvent: scrollX:"+scrollX+",distance:"+ mDistance);
                break;
            case MotionEvent.ACTION_UP:
                int scrollX1 = getScrollX();

                if (scrollX1+mDistance>0) { //左
                    if (scrollX1+mDistance>tvDelete.getWidth()/2){
                        scrollTo(tvDelete.getMeasuredWidth(),0);
                    }else {
                        scrollTo(0,0);
                    }
                }else {
                    if (scrollX1-mDistance>tvDelete.getWidth()/2){
                        scrollTo(tvDelete.getMeasuredWidth(),0);
                    }else {
                        scrollTo(0,0);
                    }
                }
                break;
        }
        return true;
    }*/

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        mViewDragHelper.processTouchEvent(event);
        return true; // 消费了事件
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        tvContant = getChildAt(0);
        tvDelete = getChildAt(1);
        mViewDragHelper = ViewDragHelper.create(this, new ViewDragHelpCallback());
    }


    class ViewDragHelpCallback extends ViewDragHelper.Callback {

        /***************************down事件***************************/
        /**
         * Touch的down事件会回调这个方法 tryCaptureView
         *
         * @return : ViewDragHelper是否继续分析处理 child的相关touch事件
         * @Child：指定要动的孩子 （哪个孩子需要动起来）
         * @pointerId: 点的标记
         */
        @Override
        public boolean tryCaptureView(View child, int pointerId) {
            Log.d(TAG, "tryCaptureView: down事件");
            return child == tvContant || child == tvDelete;
        }

        /***************************scroll滑动事件***************************/
        // Touch的move事件会回调这面这几个方法
        // clampViewPositionHorizontal
        // clampViewPositionVertical
        // onViewPositionChanged

        /**
         * 捕获了水平方向移动的位移数据
         *
         * @param child 移动的孩子View
         * @param left  父容器的左上角到孩子View的距离 (包含正负值)
         * @param dx    增量值，其实就是移动的孩子View的左上角距离控件（父亲）的距离，包含正负
         * @return 如何动
         * <p>
         * 调用完此方法，在android2.3以上就会动起来了，2.3以及以下是海动不了的
         * 2.3不兼容怎么办？没事，我们复写onViewPositionChanged就是为了解决这个问题的
         */
        @Override
        public int clampViewPositionHorizontal(View child, int left, int dx) {
            Log.d(TAG, "clampViewPositionHorizontal: scroll滑动事件 --> 增量值left:" + left);
//            return super.clampViewPositionHorizontal(child, left, dx);
            //在tvContant区域滑动，边界问题
            if (child == tvContant) {
                if (left > 0) {
                    left = 0;
                } else if (left < -tvDelete.getWidth()) {
                    left = -tvDelete.getWidth();
                }
            }

            if (child == tvDelete) {
                if (tvContant.getWidth() - tvDelete.getWidth() > left) {
                    left = tvContant.getWidth() - tvDelete.getWidth();
                }
            }
            return left;
        }

        @Override
        public int clampViewPositionVertical(View child, int top, int dy) {
            Log.d(TAG, "clampViewPositionVertical: scroll滑动事件");
            return super.clampViewPositionVertical(child, top, dy);
        }

        /**
         * 当View的位置改变时的回调
         *
         * @param changedView 哪个View的位置改变了
         * @param left        changedView的left
         * @param top         changedView的top
         * @param dx          x方向的上的增量值
         * @param dy          y方向上的增量值
         */
        @Override
        public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
            Log.d(TAG, "onViewPositionChanged: scroll滑动事件--> left:" + left);
//            super.onViewPositionChanged(changedView, left, top, dx, dy);
            invalidate();
            /*
            *
            * left : 选中的view 屏幕左上角0 与 选中view的left的 之间的距离 （view在屏幕左为负右正）
            *
            * */
            if (changedView == tvContant) {
                // left 其实是 tvcontant的left 相对 屏幕左上角（view.left - 0）
                int i = tvContant.getWidth() + left;
                int r = tvContant.getWidth() + left + tvDelete.getWidth();
                tvDelete.layout(i, 0, r, tvDelete.getHeight());
            } else {
                //left 其实是 tvDelete的left 相对 屏幕左上角（view.left - 0）;
                int i = left - tvContant.getWidth();
                int r = left;
                Log.d(TAG, "onViewPositionChanged: left:" + left);
                tvContant.layout(i, 0, r, tvContant.getHeight());
            }

        }

        /***************************up事件***************************/
        /**
         * @param releasedChild
         * @param xvel          x方向的速率
         * @param yvel          y方向的速率
         */
        @Override
        public void onViewReleased(View releasedChild, float xvel, float yvel) {
            Log.d(TAG, "onViewReleased: up事件");
            //释放是 up动作
            int left = tvContant.getLeft();
            //没必要分 tvContant和tvDelete两种情况分析  （？？有疑问？tvDetele可能有点击删除事件）
            if (-left > (tvDelete.getWidth() / 2)) {
/*                // 为什么 设一个没有联动效果
                tvContant.layout(-tvDelete.getWidth(), 0,
                        tvContant.getWidth() - tvDelete.getWidth(), tvContant.getHeight());
                tvDelete.layout(tvContant.getWidth() - tvDelete.getWidth(),
                        0, tvContant.getWidth(), tvContant.getHeight());*/

                //采用ViewDragHelper的 smoothSlideViewTo 方法让移动变得顺滑自然，不会太生硬
                //smoothSlideViewTo只是模拟了数据，但是不会真正的动起来，动起来需要调用 invalidate
                // 而 invalidate 通过调用draw()等方法之后最后还是还是会调用 computeScroll 这个方法
                // 所以，使用 smoothSlideViewTo 做过渡动画需要结合  invalidate方法 和 computeScroll方法
                // smoothSlideViewTo的动画执行时间没有暴露的参数可以设置，但是这个时间是google给我们经过大量计算给出合理时间
                mViewDragHelper.smoothSlideViewTo(tvContant,-tvDelete.getWidth(),0);
                mViewDragHelper.smoothSlideViewTo(tvDelete,tvContant.getWidth()-tvDelete.getWidth(),0);

            } else {
/*                tvContant.layout(0, 0, tvContant.getWidth(), tvContant.getHeight());
                tvDelete.layout(tvContant.getWidth(), 0,
                        tvContant.getWidth() + tvDelete.getWidth(), tvContant.getHeight());*/
                mViewDragHelper.smoothSlideViewTo(tvContant,0,0);
                mViewDragHelper.smoothSlideViewTo(tvDelete,tvContant.getWidth(),0);
            }
            invalidate();
            super.onViewReleased(releasedChild, xvel, yvel);
        }
}

    @Override
    public void computeScroll() {
        //        super.computeScroll();

        // 把捕获的View适当的时间移动，其实也可以理解为 smoothSlideViewTo 的模拟过程还没完成
        if (mViewDragHelper.continueSettling(true)) {
            invalidate();
        }
        // 其实这个动画过渡的过程大概在怎么走呢？
        // 1、smoothSlideViewTo方法进行模拟数据，模拟后就就调用invalidate();
        // 2、invalidate()最终调用computeScroll，computeScroll做一次细微动画，
        //    computeScroll判断模拟数据是否彻底完成，还没完成会再次调用invalidate
        // 3、递归调用，知道数据noni完成。

    }
}
